`timescale 1ns / 1ps
`include "top.vh"
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2021/07/08 15:44:19
// Design Name: 
// Module Name: control_logic_fsm
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////
module control_logic_fsm(input [5:0] op,
                         input clk, 
                         output pc_we_uncond,                   // 1b
                         output pc_we_cond,                     // 1b
                         output pc_source_sel,                  // 1b
                         output inst_reg_we,                    // 1b
                         output mem_we,                         // 1b
                         output mem_adr_source_sel,             // 1b
                         output regfile_we,                     // 1b
                         output [1:0] regfile_din_source_sel,   // 2b
                         output [2:0] alu_control,              // 3b
                         output alu_opA_sel,                    // 1b
                         output [1:0] alu_opB_sel,              // 2b
                         output branch_cond_sel);               // 1b
    wire [20:0] micro_code;
    reg [4:0] micro_code_adr, new_adr;
    wire sig_decode;
    
    // assign sig_decode = micro_code[];
    
    // Combinational Logic
    
    initial micro_code_adr = 0;
    
    // Output Logic
    control_store_rom microcode_rom (micro_code_adr, micro_code);
    assign {pc_we_uncond, 
            pc_we_cond,
            pc_source_sel,
            inst_reg_we,
            mem_we, 
            mem_adr_source_sel, 
            regfile_we, 
            regfile_din_source_sel,
            alu_control,
            alu_opA_sel,
            alu_opB_sel, 
            branch_cond_sel} = micro_code[20:5];
            
    // New State Logic   
    always @(*)
    begin
        if(micro_code_adr == 5'b00010)
        begin
            casex (op[5:2])
                4'b000x: new_adr = 5'b00011;
                4'b101x: new_adr = 5'b00101;
                4'b001x: new_adr = 5'b00110;
                4'b100x: new_adr = 5'b00110;
                4'b010x: new_adr = 5'b01010;
                4'b0110: new_adr = 5'b01011;
                4'b0111: new_adr = 5'b01100;
                default: new_adr = 5'b00000;
            endcase
        end
        else if(micro_code_adr == 5'b00110)
            begin
            case (op[5])
                1'b0: new_adr = 5'b01001;
                1'b1: new_adr = 5'b00111;
            endcase
            end
        else
            new_adr = micro_code[5:0];
    end
    
    // Sequencial logic
    always @(posedge clk)
        micro_code_adr <= new_adr;
    
endmodule
